const { readFile } = require('fs-extra');
const { load: yamlLoad } = require('js-yaml');
const path = require('path');
const { sh } = require('tasksfile');
const inquirer = require('inquirer');
const { IGNORE_WORKSPACE, serviceListMap } = require('../config');
const automator = require('miniprogram-automator');
const fs = require('fs');

/**
 * @description Read Workspace
 * @returns {Promise<string[]>}
 */
async function readWorkspace() {
  const workspace = yamlLoad(
    await readFile(path.resolve(process.cwd(), './pnpm-workspace.yaml'), {
      encoding: 'utf8',
    }),
    {
      json: true,
    },
  );
  return workspace.packages;
}

// 过滤得到所有项目
async function filterWorkspace() {
  // eslint-disable-next-line no-useless-catch
  try {
    const filterArgv = (await readWorkspace()).filter(
      (wr) => !IGNORE_WORKSPACE.includes(wr),
    );
    return filterArgv
      .map((argv) => ['--filter', `./"${argv}"`])
      .flatMap((argv) => argv);
  } catch (e) {
    throw e;
  }
}
async function getWorkspacePackages(filterArgv = []) {
  const stdout = await sh(
    `pnpm ls -r --depth -1 --json ${filterArgv.join(' ')}`,
    {
      async: true,
      nopipe: false,
      silent: true,
    },
  );
  if (!stdout) return [];
  return JSON.parse(stdout);
}

/**
 * @description 运行任务
 * @param options {object}
 * @param [command=start] {string} - start ｜ build ｜deploy
 * @returns {Promise<void>}
 */
async function runTask(options, command = 'start') {
  let { mode, doc } = options;
  const questions = [];
  // 是否部署文档
  if (!doc) {
    questions.push({
      type: 'confirm',
      name: 'isDoc',
      message: '是否启动文档',
      default: false,
    });
  }
  // 选择运行的服务端
  if (!mode) {
    questions.push({
      type: 'list',
      name: 'devService',
      message: '开发服务器节点',
      choices: Object.values(serviceListMap).map((option) => ({
        name: option.name,
        value: option.mode,
        checked: option.checked,
      })),
    });
  }

  const filterArgv = (await filterWorkspace()) || [];
  const workspacePackages = await getWorkspacePackages(filterArgv);
  // 多个应用项目
  if (workspacePackages.length > 1) {
    const choices = workspacePackages.map((item) => ({
      title: item.name,
      value: item.name,
    }));
    questions.push({
      type: 'checkbox',
      message: `选择要运行的包 ${command} 脚本: `,
      name: 'packages',
      choices,
      validate: function (val) {
        if (val && val.length) return true;
        return '请至少选择一个: ';
      },
    });
  } else if (workspacePackages.length === 0) {
    return console.log(`暂无项目可${command}`);
  }
  const { devService, isDoc, packages } = await inquirer.prompt(questions);

  const appPackages =
    packages || workspacePackages.map((workspace) => workspace.name);

  mode = mode || devService;
  doc = !!doc || isDoc;
  // console.log(mode, doc, packages);
  const scriptArgv = appPackages
    .map((packageName) => ['--filter', packageName])
    .flatMap((argvItem) => argvItem);

  // 执行 应用下的所有命令
  await sh(`pnpm -w run turbo:${command} ${scriptArgv.join(' ')}`, {
    async: true,
    nopipe: true,
    env: {
      ...process.env,
      MODE: mode,
      NODE_ENV: command === 'start' ? 'development' : 'production',
      PRO_DOCS: Number(doc),
    },
  });
}

// 启动开发者小程序
async function startWxMiniprogram() {
  // 默认macos 开发者小程序安装路径
  let cliPath = '/Applications/wechatwebdevtools.app/Contents/MacOS/cli';
  const isDev = process.env.NODE_ENV === 'development';
  const projectPath = isDev ? './dist/dev/mp-weixin' : './dist/build/mp-weixin';

  if (process.platform === 'win32') {
    const winPathList = process.env.Path.split(';');
    const wx = winPathList
      .filter((envPath) => envPath.indexOf('\\dll') !== -1)
      .filter((path) => {
        return fs.existsSync(path.replace('\\dll', '\\微信开发者工具.exe'));
      })
      .map((path) => {
        return path.replace('\\dll', '\\cli.bat');
      });
    cliPath = wx?.[0];
    if (!cliPath) return;
  }
  const miniProgram = await automator.launch({
    cliPath, // 工具 cli 位置，如果你没有更改过默认安装位置，可以忽略此项
    projectPath, // 开发中/打包后 项目文件地址
  });
  const page = await miniProgram.reLaunch('/pages/index/index');
  await page.waitFor(500);
}

async function openHBuildX() {
  // 打开 hbuild
  const HBuilderX = '/Applications/HBuilderX.app';
  await sh(`open ${HBuilderX}`, {
    async: true,
    nopipe: true,
  });
}

async function openHBuildXPro(command) {
  // 默认macos 开发者小程序安装路径
  let cliPath = '/Applications/HBuilderX.app/Contents/MacOS/cli';
  const commandPathMap = {
    start: path.resolve(process.cwd(), './dist/dev/app'),
    build: path.resolve(process.cwd(), './dist/build/app'),
  };
  const projectPath = commandPathMap[command] || commandPathMap['start'];
  await sh(`${cliPath} project open --path ${projectPath}`, {
    async: true,
    nopipe: true,
  });
}

module.exports = {
  filterWorkspace,
  getWorkspacePackages,
  runTask,
  startWxMiniprogram,
  openHBuildX,
  openHBuildXPro,
};
